...loading
2024-10-21
자바스크립트는 프로토타입 기반의 언어이다.
자바스크립트는 함수에 자동으로 객체인 프로토타입 프로퍼티를 생성한다.
new 연산자로 해당 함수의 인스턴스가 발생할 경우, 숨겨진 프로퍼티값인 _ proto _라는 숨겨진 객체가 생성된다.
: 프로토타입 사용의 특징을 코드 예시를 통해 설명해보려한다.
let Person = function(name) { this._name = name; } Person.prototype.getName() = function() { return this._name; }
생성자 함수를 선언하고 해당함수의 프로토타입 프로퍼티에 getName메서드를 추가한다.
여기서 만약 인스턴스를 생성하여 getName 메서드를 상속시키려면 어떻게 해야할까?
let tukee = new Person("Tukee"); tukee.__proto__.getName(); // undefined
이상하게도 상속받은 메서드의 결과가 undefined다. Tukee가 나올 것이라 기대할 수 있는데 왜 undefined가 나온 것일까? undefined가 나왔으니 getName메서드는 실행된게 맞을텐데 결과가 원하지 않는 값이다.
그 이유는 getName메서드가 호출될 때 this가 tukee._ proto__에 바인딩되기 때문이다. (해당 규칙은 this파트에서 알아보았다) 그리고 tukee. proto _에는 getName이라는 메서드는 있다. 그러나 name이라는 프로퍼티가 없다. 즉 name이라는 값이 없기 때문에 메서드 자체는 실행되지만 반환되는 값이 undefined가 되는 것이다.
자, 그렇다면 어떻게하면 Tukee가 출력될 수 있을까?
tukee.getName() // Tukee
tukee에 메서드를 호출하면 된다. tukee에는 name 프로퍼티에 'Tukee'라는 데이터가 있기 때문에 위의 결과가 출력된 것이다.
그런데,, 여기에서 또 이상한 점이 있다. 어떻게 _proto _객체에 대한 접근도 없이 메서드를 상속받을 수 있었을까? 생성자함수의 prototype을 참조하려면 proto에 접근해야하는 것 아닌가?
이것이 자바스크립트 프로토타입 시스템의 특이한 점이다. 자바스크립트는 처음부터 proto객체를 생략가능하게 설계되었다. 그렇게 만들어졌다. 따라서 proto라는 객체를 생략하더라도 prototype의 속성을 상속받을 수 있는 것이다.
이로써 생성자함수의 인스턴스는 마치 자신의 것처럼 생성자 함수의 프로퍼티를 사용할 수 있게 된다.
위의 설명에서 인스턴스 객체는 생성자의 프로퍼티를 상속받아 자신의 것처럼 사용할 수 있음을 알아보았다. 그런데 만약 인스턴스가 프로토타입의 메서드와 똑같은 이름의 메서드를 생성하면 어떻게 될까?
예시를 들어보겠다. (이전과 같은 예시다)
let Person = function(name) { this._name = name; } Person.prototype.getName() = function() { return this._name; } let tukee = new Person("Tukee"); tukee.getName = function() { return "My name is Tukee Kim"; } tukee.getName() // My name is Tukee Kim
예시와 같이 인스턴스가 같은 이름의 메서드를 할당받고 호출할 경우, 프로토타입의 메서드가 아닌 최신의 메서드가 동작한다. 이러한 결과를 메서드 오버라이드라 한다.
그렇다면 해당 기존 생성자 프로토타입의 getName메서드는 어떻게 된걸까?
proto는 생성자의 prototype을 참조하기 때문에 기존의 메서드 원본은 최신 메서드로 덮어씌워지는걸까?
결론은 아니다. prototype의 원본은 그대로 유지되고 tukee라는 인스턴스의 프로퍼티에 최신 메서드가 포함되는 것 뿐이다.
위처럼 메서드 오버라이드가 발생하는 것은 자바스크립트 엔진이 메서드를 찾을 때, 가장 가까운 대상인 호출자의 프로퍼티부터 상위 생성자의 프로토타입을 타고가며 실행 가능한 메서드를 찾아나가기 때문이다.
프로토타입 체이닝은 위의 설명한 메서드 오버라이드와 같은 맥락으로 이해할 수 있다.
자바스크립트의 객체는 _ptoto _를 통해 얽혀져 있다. 자바스크립트는 이렇게 구성된 체인을 타며 실행가능한 메서드를 찾을 수 있게 된다. 즉 메서드 오버라이드는 프로토타입 체인과 직결되는 것이다.
객체의 프로토타입을 쭉 타고가서 근원지까지 가면 최상단인 Object.prototype에 도달하게 된다. 이 Object.prototype에는 모든 데이터에서 사용할 수 있는 범용적인 메서드가 존재한다.(기본적으로 사용자가 정의한 프로퍼티나 메서드가 존재하지는 않는다)
Comments